package com.pacvue.utils;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

@Slf4j
public class SpELUtils {

    private static final ExpressionParser parser = new SpelExpressionParser();
    private static final DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
    
    // 缓存已解析的表达式，提高性能
    private static final ConcurrentMap<String, Expression> EXPRESSION_CACHE = new ConcurrentHashMap<>();
    
    // 缓存方法参数名，避免重复反射获取
    private static final ConcurrentMap<Method, String[]> PARAMETER_NAMES_CACHE = new ConcurrentHashMap<>();

    public static String parse(String key, ProceedingJoinPoint joinPoint) {
        if (key == null || key.trim().isEmpty()) {
            return defaultKey(joinPoint);
        }

        try {
            // 尝试解析 SpEL 表达式
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            
            // 从缓存获取参数名
            String[] paramNames = PARAMETER_NAMES_CACHE.computeIfAbsent(method, 
                m -> discoverer.getParameterNames(m));
            
            Object[] args = joinPoint.getArgs();

            // 从缓存获取表达式
            Expression expression = EXPRESSION_CACHE.computeIfAbsent(key, 
                k -> parser.parseExpression(k));

            EvaluationContext context = new StandardEvaluationContext();
            if (paramNames != null) {
                for (int i = 0; i < paramNames.length && i < args.length; i++) {
                    context.setVariable(paramNames[i], args[i]);
                }
            }

            String result = expression.getValue(context, String.class);
            if (log.isDebugEnabled()) {
                log.debug("SpEL表达式解析成功 - key: {}, result: {}", key, result);
            }
            return result;
            
        } catch (Exception e) {
            log.warn("SpEL表达式解析失败，使用原始key - key: {}, error: {}", key, e.getMessage());
            // 如果 SpEL 解析失败，回退为普通字符串 key
            return key;
        }
    }

    private static String defaultKey(ProceedingJoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        return method.getDeclaringClass().getName() + ":" + method.getName();
    }
    
    /**
     * 清理缓存（可选，用于内存管理）
     */
    public static void clearCache() {
        EXPRESSION_CACHE.clear();
        PARAMETER_NAMES_CACHE.clear();
        if (log.isDebugEnabled()) {
            log.debug("SpEL缓存已清理");
        }
    }
}
